home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 2 / Atari Mega Archive CD - Volume 2.iso / minix / up1510b.tgz / up1510b / src / commands / ps.c < prev    next >
C/C++ Source or Header  |  1990-07-23  |  19KB  |  628 lines

  1. /* ps - print status            Author: Peter Valkenburg */
  2.  
  3. /* ps.c, Peter Valkenburg (valke@psy.vu.nl), january 1990.
  4.  *
  5.  * This is a V7 ps(1) look-alike for MINIX 1.5.0.  It can use a database with
  6.  * information on system addresses as an extra, and has some additional fields.
  7.  * It does not support the 'k' option (i.e. cannot read memory from core file).
  8.  * If you want to compile this for non-IBM PC architectures, the header files
  9.  * require that you have your CHIP, MACHINE etc. defined.
  10.  *
  11.  * VERY IMPORTANT NOTE:
  12.  *    To use ps, kernel/kernel, fs/fs, and mm/mm must be in the /usr/src
  13.  *    (or the #includes below must be changed).  Furthermore, all of
  14.  *    must contain symbol tables.  This can be arranged using the -s flag
  15.  *    and the ast program.  For example in fs, one would have
  16.  *
  17.  *    asld -s -i -o fs $l/head.s $(obj) $l/libc.a $l/end.s >symbol.out
  18.  *    ast -X fs        # include symbol.out in fs
  19.  *
  20.  */
  21.  
  22. /*
  23.  * Most fields are similar to V7 ps(1), except for CPU, NICE, PRI which are
  24.  * absent, RECV which replaces WCHAN, and RUID and PGRP that are extras.
  25.  * The info is obtained from the following fields of proc, mproc and fproc:
  26.  * F    - kernel status field, p_flags
  27.  * S    - kernel status field, p_flags; mm status field, mp_flags (R if p_flags
  28.  *       is 0; Z if mp_flags == HANGING; T if mp_flags == STOPPED; else W).
  29.  * UID    - mm eff uid field, mp_effuid
  30.  * RUID    - mm real uid field, mp_realuid
  31.  * PID    - mm pid field, mp_pid
  32.  * PPID    - mm parent process index field, mp_parent (used as index in proc).
  33.  * PGRP - mm process group id mp_procgrp
  34.  * ADDR    - kernel physical text address, p_map[T].mem_phys
  35.  * SZ    - kernel physical stack address + stack size - physical text address,
  36.  *       p_map[S].mem_phys + p_map[S].mem_len - p_map[T].mem_phys
  37.  * RECV    - kernel process index field for message receiving, p_getfrom
  38.  *      If sleeping, mm's mp_flags, or fs's fp_task are used for more info.
  39.  * TTY    - fs controlling tty device field, fs_tty.
  40.  * TIME    - kernel user + system times fields, user_time + sys_time
  41.  * CMD    - system process index (converted to mnemonic name obtained by reading
  42.  *      tasktab array from kmem), or user process argument list (obtained by
  43.  *      reading reading stack frame; the resulting address is used to get
  44.  *      the argument vector from user space and converted into a concatenated
  45.  *      argument list).
  46.  */        
  47.  
  48. #include <minix/config.h>
  49. #include <limits.h>
  50. #include <sys/types.h>
  51.  
  52. #include <minix/const.h>
  53. #undef EXTERN                /* <minix/const.h> defined this */
  54. #define EXTERN                /* so we get proc, mproc and fproc */
  55. #include <minix/type.h>
  56.  
  57. #include "../kernel/const.h"
  58. #include "../kernel/type.h"
  59. #include "../kernel/proc.h"
  60. #undef printf                /* kernel's const.h defined this */
  61.  
  62. #include "../mm/mproc.h"
  63. #include "../fs/fproc.h"
  64. #include "../fs/const.h"
  65. #undef printf                /* fs's const.h defined this */
  66.  
  67.  
  68. /*----- ps's local stuff below this line ------*/
  69.  
  70. #include <minix/com.h>
  71. #include <fcntl.h>
  72. #include <a.out.h>
  73. #include <stdio.h>
  74.  
  75. #define mindev(dev)    (((dev)>>MINOR) & 0377)    /* yield minor device */
  76. #define majdev(dev)    (((dev)>>MAJOR) & 0377)    /* yield major device */
  77.  
  78. #define    TTY_MAJ        4            /* fixed tty major device */
  79.  
  80. /* macro to convert memory offsets to rounded kilo-units */
  81. #define    off_to_k(off)    ((unsigned) (((off) + 512) / 1024))
  82.  
  83. /* what we think the relevant identifiers in the namelists are */
  84. #define    ID_PROC        "_proc"        /* from kernel namelist */
  85. #define    ID_MPROC    "_mproc"    /* from mm namelist */
  86. #define    ID_FPROC    "_fproc"    /* from fs namelist */
  87. #define    ID_TASKTAB    "_tasktab"    /* from kernel namelist */
  88.  
  89. /*
  90.  * Structure for system address info (also layout of ps's database).
  91.  */
  92. typedef struct {
  93.     struct nlist ke_proc[2], ke_tasktab[2];
  94.     struct nlist mm_mproc[2];
  95.     struct nlist fs_fproc[2];
  96. } sysinfo_t;
  97.  
  98. sysinfo_t sysinfo;            /* sysinfo holds actual system info */
  99.  
  100. #define    NAME_SIZ    (sizeof(sysinfo.ke_proc[0].n_name))    /* 8 chars */
  101.  
  102. /* what we think the identfiers of the imported variables in this program are */
  103. #define    PROC    proc
  104. #define    MPROC    mproc
  105. #define    FPROC    fproc
  106. #define    TASKTAB    tasktab
  107.  
  108. /* default paths for system binaries */
  109. #if (CHIP == M68000)
  110. #define KERNEL_PATH    "/usr/src/kernel/kernel.mix"
  111. #define MM_PATH        "/usr/src/mm/mm.mix"
  112. #define FS_PATH        "/usr/src/fs/fs.mix"
  113. #else
  114. #define KERNEL_PATH    "/usr/src/kernel/kernel"
  115. #define MM_PATH        "/usr/src/mm/mm"
  116. #define FS_PATH        "/usr/src/fs/fs"
  117. # endif
  118.  
  119. #define    KMEM_PATH    "/dev/kmem"    /* opened for kernel proc table */
  120. #define    MEM_PATH    "/dev/mem"    /* opened for mm/fs + user processes */
  121.  
  122. int kmemfd, memfd;            /* file descriptors of [k]mem */
  123.  
  124. #define DBASE_PATH    "/etc/psdatabase"    /* path of ps's database */
  125. #define DBASE_MODE    0644            /* mode for ps's database */
  126.  
  127. /* paths for system binaries (not relevant if database is used) */
  128. char *kpath = KERNEL_PATH;
  129. char *mpath = MM_PATH;
  130. char *fpath = FS_PATH;
  131.  
  132. struct tasktab tasktab[NR_TASKS + INIT_PROC_NR + 1];    /* task table */
  133.  
  134. /*
  135.  * Short and long listing formats:
  136.  *
  137.  *   PID TTY  TIME CMD
  138.  * ppppp  ttmmm:ss ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
  139.  * 
  140.  *   F S UID   PID  PPID  PGRP ADDR  SZ        RECV TTY  TIME CMD
  141.  * fff s uuu ppppp ppppp ppppp aaaa sss rrrrrrrrrrr  ttmmm:ss cccccccccccccccccccc
  142.  * (RAMDSK) FS
  143.  * or
  144.  * (PAUSE) MM
  145.  */
  146. #define S_HEADER "  PID TTY  TIME CMD\n"
  147. #define S_FORMAT "%5d  %3s%3ld:%02ld %.62s\n"
  148. #define L_HEADER "  F S UID   PID  PPID  PGRP ADDR  SZ        RECV TTY  TIME CMD\n"
  149. #define L_FORMAT "%3o %c %3d %5d %5d %5d %4d %3d %11s  %3s%3ld:%02ld %.19s\n"
  150.  
  151. struct pstat {                /* structure filled by pstat() */
  152.     dev_t ps_dev;            /* major/minor of controlling tty */
  153.     uid_t ps_ruid;            /* real uid */
  154.     uid_t ps_euid;            /* effective uid */
  155.     pid_t ps_pid;            /* process id */
  156.     pid_t ps_ppid;            /* parent process id */
  157.     int ps_pgrp;            /* parent process id */
  158.     int ps_flags;            /* kernel flags */
  159.     int ps_mflags;            /* mm flags */
  160.     int ps_ftask;            /* (possibly pseudo) fs suspend task */
  161.     char ps_state;            /* process state */
  162.     size_t ps_tsize;        /* text size (in bytes) */
  163.     size_t ps_dsize;        /* data size (in bytes) */
  164.     size_t ps_ssize;        /* stack size (in bytes) */
  165.     off_t ps_text;            /* physical text offset */
  166.     off_t ps_data;            /* physical data offset */
  167.     off_t ps_stack;            /* physical stack offset */
  168.     int ps_recv;            /* process number to receive from */
  169.     time_t ps_utime;        /* accumulated user time */
  170.     time_t ps_stime;        /* accumulated system time */
  171.     char *ps_args;            /* concatenated argument string */
  172. };
  173.  
  174. /* ps_state field values in pstat struct above */
  175. #define    Z_STATE        'Z'        /* Zombie */
  176. #define    W_STATE        'W'        /* Waiting */
  177. #define    S_STATE        'S'        /* Sleeping */
  178. #define    R_STATE        'R'        /* Runnable */
  179. #define    T_STATE        'T'        /* stopped (Trace) */
  180.  
  181. /*
  182.  * Tname returns mnemonic string for dev_nr.  This is "?" for unknown maj/min
  183.  * pairs.  It is utterly rigid in this implementation...
  184.  */
  185. char *tname(dev_nr)
  186. {
  187.     static char buf[4];
  188.     
  189.     if (majdev(dev_nr) != TTY_MAJ ||    /* yuchhh! */
  190.         mindev(dev_nr) < 0 || mindev(dev_nr) >= 100)
  191.         return "?  ";
  192.     if (mindev(dev_nr) == 0)
  193.         return "co ";
  194.  
  195.     sprintf(buf, "t%-2d", mindev(dev_nr));
  196.     return buf;
  197. }
  198.  
  199. /* return canonical task name of task p_nr; overwritten on each call */
  200. char *taskname(p_nr)
  201. {
  202.     char *cp;
  203.     
  204.     if (p_nr < -NR_TASKS || p_nr > INIT_PROC_NR)
  205.         return "?";
  206.     
  207.     /* strip trailing blanks for right-adjusted output */
  208.     for (cp = tasktab[p_nr + NR_TASKS].name; *cp != '\0'; cp++)
  209.         if (*cp == ' ')
  210.             break;
  211.     *cp = '\0';        
  212.     
  213.     return tasktab[p_nr + NR_TASKS].name;
  214. }
  215.  
  216. /*
  217.  * Prrecv prints the RECV field for process with pstat buffer pointer bufp.
  218.  * This is either "ANY", "taskname", or "(blockreason) taskname".
  219.  */
  220. char *prrecv(bufp)
  221. struct pstat *bufp;
  222. {
  223.     char *blkstr, *task;        /* reason for blocking and task */
  224.     static char recvstr[20];
  225.  
  226.     if (bufp->ps_recv == ANY)
  227.         return "ANY";
  228.  
  229.     task = taskname(bufp->ps_recv);
  230.     if (bufp->ps_state != S_STATE)
  231.         return task;
  232.     
  233.     blkstr = "?";
  234.     if (bufp->ps_recv == MM_PROC_NR) {
  235.         if (bufp->ps_mflags & PAUSED)
  236.             blkstr = "pause";
  237.         else if (bufp->ps_mflags & WAITING)
  238.             blkstr = "wait";
  239.     }
  240.     else if (bufp->ps_recv == FS_PROC_NR) {
  241.         if (-bufp->ps_ftask == XOPEN)
  242.             blkstr = "xopen";
  243.         else if (-bufp->ps_ftask == XPIPE)
  244.             blkstr = "xpipe";
  245.         else
  246.             blkstr = taskname(-bufp->ps_ftask);    
  247.     }
  248.     
  249.     (void) sprintf(